﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;

namespace Cherry.Agile.Framework
{
    /// <summary>
    /// 异常处理
    /// </summary>
    public class ExceptionHandler:IExceptionHandler
    {
        Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.ExceptionManager _impl;

        /// <summary>
        /// 构造函数
        /// </summary>
        public ExceptionHandler()
        {
            ExceptionPolicyFactory policyFactory = new ExceptionPolicyFactory();
            _impl = policyFactory.CreateManager();

        }

        #region IExceptionHandler Members

        /// <summary>
        /// 根据配置的policyName处理指定的Exception <see cref="Exception"/>对象.
        /// </summary>
        /// <param name="exceptionToHandle">一个Exception<see cref="Exception"/> 对象.</param>
        /// <param name="policyName">处理策略的名字.</param>
        /// <param name="exceptionToThrow">新的要抛出的Exception <see cref="Exception"/>.</param>
        /// <remarks>
        /// 如果Exception<paramref name="exceptionToThrow"/>是langword="null"<see langword="null"/>被建议重新抛出,
        /// 那么原来的Exception <paramref name="exceptionToHandle"/> 应该被重新抛出; 否则,
        /// 返回在 <paramref name="exceptionToThrow"/>的Exception应该会被抛出.
        /// </remarks>
        /// <returns>
        /// 重新抛出Exception或者不抛. 
        /// </returns>
        /// <example>
        /// 下面是应用exception handling framework的例子.
        /// <code>
        /// try
        ///	{
        ///		DoWork();
        ///	}
        ///	catch (Exception e)
        ///	{
        ///	    Exception exceptionToThrow;
        ///		if (exceptionManager.HandleException(e, name, out exceptionToThrow))
        ///		{
        ///		  if(exceptionToThrow == null)
        ///		    throw;
        ///		  else
        ///		    throw exceptionToThrow;
        ///		}
        ///	}
        /// </code>
        /// </example>
        /// <seealso cref="ExceptionManager.HandleException(Exception, string)"/>
        public bool HandleException(System.Exception exceptionToHandle, string policyName, out System.Exception exceptionToThrow)
        {
            return _impl.HandleException(exceptionToHandle, policyName, out exceptionToThrow);
        }

        /// <summary>
        /// 根据配置的policyName处理指定的Exception <see cref="Exception"/>对象.
        /// </summary>
        /// <param name="exceptionToHandle">一个Exception<see cref="Exception"/> 对象.</param>
        /// <returns>重新抛出Exception或者不抛</returns>
        public bool HandleException(System.Exception exceptionToHandle)
        {
            const string policyName = "Global";
            return _impl.HandleException(exceptionToHandle, policyName);
        }

        /// <summary>
        ///   根据配置的policyName处理指定的Exception <see cref="Exception"/>对象.  
        /// </summary>
        /// <param name="exceptionToHandle">一个Exception<see cref="Exception"/> 对象.</param>
        /// <param name="policyName">处理策略的名字.</param>
        /// <returns>
        /// 重新抛出Exception或者不抛. 
        /// </returns>
        /// <example>
        /// 下面是应用exception handling framework的例子.
        /// <code>
        /// try
        ///	{
        ///		DoWork();
        ///	}
        ///	catch (Exception e)
        ///	{
        ///		if (exceptionManager.HandleException(e, name)) throw;
        ///	}
        /// </code>
        /// </example>
        /// <seealso cref="ExceptionManager.Process"/>
        public bool HandleException(System.Exception exceptionToHandle, string policyName)
        {
            return _impl.HandleException(exceptionToHandle, policyName);
        }
        /// <summary>
        /// 执行应用程序提供的代理<paramref name="action"/>和根据配置的policyName处理Exception
        /// </summary>
        /// <param name="action">要执行的代理.</param>
        /// <param name="policyName">处理策略的名字.</param>        
        /// <example>
        /// 下面是应用该方法的例子.
        /// <code>
        ///		exceptionManager.Process(() => { DoWork(); }, "policy");
        /// </code>
        /// </example>
        /// <seealso cref="ExceptionManager.HandleException(Exception, string)"/>
        public void Process(Action action, string policyName)
        {
            _impl.Process(action, policyName);
        }
        /// <summary>
        /// 执行应用程序提供的代理<paramref name="action"/>和根据配置的policyName <paramref name="policyName"/>处理Exception
        /// </summary>
        /// <typeparam name="TResult">代理返回值的类型 <paramref name="action"/>.</typeparam>
        /// <param name="action">执行的代理.</param>
        /// <param name="defaultResult">
        /// 如果发生exception就会返回这个值并且异常处理机制自动处理掉异常不会重新抛出.</param>
        /// <param name="policyName">处理机制的名字.</param>
        /// <returns>如果没有异常抛出就会返回代理<paramref name="action"/>执行的结果. 
        /// 如果有异常抛出并用琐有指定重新抛出异常那么就会返回defaultResult<paramref name="defaultResult"/>.
        /// </returns>
        public TResult Process<TResult>(Func<TResult> action, TResult defaultResult, string policyName)
        {
            return _impl.Process<TResult>(action, defaultResult, policyName);
        }
        /// <summary>
        /// 执行应用程序提供的代理<paramref name="action"/>和根据配置的policyName <paramref name="policyName"/>处理Exception
        /// </summary>
        /// <typeparam name="TResult">代理返回值的类型 <paramref name="action"/>.</typeparam>
        /// <param name="action">执行的代理.</param>
        /// <param name="policyName">处理机制的名字.</param>
        /// <returns>如果没有异常抛出就会返回代理<paramref name="action"/>执行的结果. 
        /// 如果有异常抛出并用琐有指定重新抛出异常那么就会返回默认值<typeparamref name="TResult"/>.
        /// </returns>
        public TResult Process<TResult>(Func<TResult> action, string policyName)
        {
            return _impl.Process<TResult>(action, policyName);
        }
        #endregion
    }
}
